package com.diver.flinkdemo.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.diver.flinkdemo.entity.PushData;
import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.objenesis.Objenesis;
import org.objenesis.ObjenesisStd;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisPubSub;
import redis.clients.jedis.exceptions.JedisDataException;

import javax.annotation.PostConstruct;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author LuJW
 * @date 2023/3/29 13:36
 */
@Slf4j
public class JedisUtil {
//    private static Logger log = LoggerFactory.getLogger(JedisUtil.class);
    private static JedisPool jedisPool;

    static{
        try {
            JedisPoolConfig config = new JedisPoolConfig();
            config.setMaxIdle(8);
            config.setMaxTotal(18);
            jedisPool = new JedisPool(config,"172.16.100.72",8910,10000,"YUIHkwen12423qIUKwefhausildfk");
            log.info("初始化jedisPool->{}",jedisPool);
        } catch (Exception e) {
            if(log.isDebugEnabled()){
                e.printStackTrace();
            }
        }
    }
//    @PostConstruct
    public static void poolInit() {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxIdle(8);
        config.setMaxTotal(18);
        jedisPool = new JedisPool(config,"172.16.100.72",8910,10000,"YUIHkwen12423qIUKwefhausildfk");
        log.info("初始化jedisPool->{}",jedisPool);
    }

    public static Jedis getJedis() {
        return jedisPool.getResource();
    }

    public static void returnJedis(Jedis jedis){
        try {
            jedisPool.returnResource(jedis);
        } catch (Exception e) {
            // TODO: handle exception
            if(log.isDebugEnabled()){
                e.printStackTrace();
            }
        }
    }

    private static final int DEFAULT_SETEX_TIMEOUT = 60 * 60;// setex的默认时间

    /**
     * 添加一个字符串值,成功返回1,失败返回0
     *
     * @param key
     * @param value
     * @return
     */
    public static boolean set(String key, String value) {
        if (isValueNull(key, value)) {
            return false;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.set(key, value).equalsIgnoreCase("ok");
        } finally {
            returnJedis(jedis);
        }

    }

    /**
     * 缓存一个字符串值,成功返回1,失败返回0,默认缓存时间为1小时,以本类的常量DEFAULT_SETEX_TIMEOUT为准
     *
     * @param key
     * @param value
     * @return
     */
    public static boolean setEx(String key, String value) {
        if (isValueNull(key, value)) {
            return false;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.setex(key, DEFAULT_SETEX_TIMEOUT, value).equalsIgnoreCase("ok");
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 缓存一个字符串值,成功返回1,失败返回0,缓存时间以timeout为准,单位秒
     *
     * @param key
     * @param value
     * @param timeout
     * @return
     */
    public static boolean setEx(String key, String value, int timeout) {
        if (isValueNull(key, value)) {
            return false;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.setex(key, timeout, value).equalsIgnoreCase("ok");
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 添加一个指定类型的对象,成功返回1,失败返回0
     *
     * @param key
     * @param value
     * @return
     */
    public static <T> boolean set(String key, T value) {
        if (isValueNull(key, value)) {
            return false;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            if (value instanceof String) {
                jedis.set(key,(String) value);
                return true;
            }else {
                jedis.set(key.getBytes(),JSON.toJSONString(value).getBytes(StandardCharsets.UTF_8));
                return true;
            }
        } finally {
            returnJedis(jedis);
        }
    }

    public static boolean setExpire(String key,int expire) {
        if (isValueNull(key,expire)) {
            return false;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            Long expire1 = jedis.expire(key, expire);
            return expire1.intValue() == 1;
        } finally {
            returnJedis(jedis);
        }

    }

    /**
     * 缓存一个指定类型的对象,成功返回1,失败返回0,默认缓存时间为1小时,以本类的常量DEFAULT_SETEX_TIMEOUT为准
     *
     * @param key
     * @param value
     * @return
     */
    public static <T> boolean setEx(String key, T value) {
        if (isValueNull(key, value)) {
            return false;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            byte[] data = enSeri(value);
            return jedis.setex(key.getBytes(), DEFAULT_SETEX_TIMEOUT, data).equalsIgnoreCase("ok");
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 缓存一个指定类型的对象,成功返回1,失败返回0,缓存时间以timeout为准,单位秒
     *
     * @param key
     * @param value
     * @param timeout
     * @return
     */
    public static <T> boolean setEx(String key, T value, int timeout) {
        if (isValueNull(key, value)) {
            return false;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            byte[] data = enSeri(value);
            return jedis.setex(key.getBytes(), timeout, data).equalsIgnoreCase("ok");
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 将一个数值+1,成功返回+后的结果,失败返回null
     *
     * @param key
     * @return
     * @throws JedisDataException
     */
    public static Long incr(String key) throws JedisDataException {
        if (isValueNull(key)) {
            return null;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.incr(key);
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 将一个数值-1,成功返回-后的结果,失败返回null
     *
     * @param key
     * @return
     * @throws JedisDataException
     */
    public static Long decr(String key) throws JedisDataException {
        if (isValueNull(key)) {
            return null;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.decr(key);
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 添加一个字符串值到list中,,成功返回1,失败返回0
     *
     * @param key
     * @param value
     * @return
     */
    public static boolean setList(String key, String... value) {
        if (isValueNull(key, value)) {
            return false;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            Long result = jedis.rpush(key, value);
            return result != null && result != 0;
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 缓存一个字符串值到list中,全部list的key默认缓存时间为1小时,成功返回1,失败返回0
     *
     * @param key
     * @param value
     * @return
     */
    public static boolean setExList(String key, String... value) {
        if (isValueNull(key, value)) {
            return false;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            Long result = jedis.rpush(key, value);
            jedis.expire(key, DEFAULT_SETEX_TIMEOUT);
            return result != null && result != 0;

        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 缓存一个字符串值到list中,全部list的key缓存时间为timeOut,单位为秒,成功返回1,失败返回0
     *
     * @param key
     * @param value
     * @return
     */
    public static boolean setExList(String key, int timeOut, String... value) {
        if (isValueNull(key, value)) {
            return false;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            Long result = jedis.rpush(key, value);
            jedis.expire(key, timeOut);
            return result != null && result != 0;

        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 添加一个<T>类型对象值到list中,成功返回1,失败返回0
     *
     * @param key
     * @param value
     * @return
     */
    @SafeVarargs
    public static <T> boolean setList(String key, T... value) {
        if (isValueNull(key, value)) {
            return false;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            int res = 0;
            for (T t : value) {
                byte[] data = enSeri(t);
                Long result = jedis.rpush(key.getBytes(), data);
                if (result != null && result != 0) {
                    res++;
                }
            }
            return res != 0;
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 缓存一个<T>类型对象值到list中,全部list的key默认缓存时间为1小时,成功返回1,失败返回0
     *
     * @param key
     * @param value
     * @return
     */
    @SafeVarargs
    public static <T> boolean setExList(String key, T... value) {
        if (isValueNull(key, value)) {
            return false;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            int res = 0;
            for (T t : value) {
                byte[] data = enSeri(t);
                Long result = jedis.rpush(key.getBytes(), data);
                if (result != null && result != 0) {
                    res++;
                }
            }
            jedis.expire(key, DEFAULT_SETEX_TIMEOUT);
            if (res != 0) {
                return true;
            } else {
                return false;
            }
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 缓存一个<T>类型对象值到list中,全部list的key缓存时间为timeOut,单位秒,成功返回1,失败返回0
     *
     * @param key
     * @param value
     * @return
     */
    @SafeVarargs
    public static <T> boolean setExList(String key, int timeOut, T... value) {
        if (isValueNull(key, value)) {
            return false;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            int res = 0;
            for (T t : value) {
                byte[] data = enSeri(t);
                Long result = jedis.rpush(key.getBytes(), data);
                if (result != null && result != 0) {
                    res++;
                }
            }
            jedis.expire(key, timeOut);
            return res != 0;
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 添加一个List集合成功返回1,失败返回0
     *
     * @param key
     * @param value
     * @return
     * @throws IOException
     * @throws RuntimeException
     */
    public static <T> int setList(String key, List<T> value) throws RuntimeException, IOException {
        if (isValueNull(key, value)) {
            return 0;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            byte[] data = enSeriList(value);
            if (jedis.set(key.getBytes(), data).equalsIgnoreCase("ok")) {
                return 1;
            } else {
                return 0;
            }
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 缓存一个List<T>集合,成功返回1,失败返回0,默认缓存时间为1小时,以本类的常量DEFAULT_SETEX_TIMEOUT为准
     *
     * @param key
     * @param value
     * @return
     * @throws IOException
     * @throws RuntimeException
     */

    public static <T> int setExList(String key, List<T> value) throws RuntimeException, IOException {
        if (isValueNull(key, value)) {
            return 0;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            byte[] data = enSeriList(value);
            if (jedis.setex(key.getBytes(), DEFAULT_SETEX_TIMEOUT, data).equalsIgnoreCase("ok")) {
                return 1;
            } else {
                return 0;
            }
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 缓存一个List<T>集合,成功返回1,失败返回0,缓存时间以timeout为准,单位秒
     *
     * @param key
     * @param value
     * @param timeout
     * @return
     * @throws IOException
     * @throws RuntimeException
     */
    public static <T> int setExList(String key, List<T> value, int timeout) throws RuntimeException, IOException {
        if (isValueNull(key, value)) {
            return 0;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            byte[] data = enSeriList(value);
            if (jedis.setex(key.getBytes(), timeout, data).equalsIgnoreCase("ok")) {
                return 1;
            } else {
                return 0;
            }
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 添加一个字符串到set,如果key存在就在就最追加,如果key不存在就创建,成功返回1,失败或者没有受影响返回0
     *
     * @param key
     * @param value
     * @return
     */
    public static int setSet(String key, String... value) {
        if (isValueNull(key, value)) {
            return 0;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            Long result = jedis.sadd(key, value);
            if (result != null && result != 0) {
                return 1;
            } else {
                return 0;
            }
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 添加一个字符串set,如果key存在就在就最追加,整个set的key默认一小时后过期,如果key存在就在可以种继续添加,如果key不存在就创建,成功返回1,失败或者没有受影响返回0
     *
     * @param key
     * @param value
     * @return
     */
    public static int setExSet(String key, String... value) {
        if (isValueNull(key, value)) {
            return 0;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            Long result = jedis.sadd(key, value);
            jedis.expire(key, DEFAULT_SETEX_TIMEOUT);
            if (result != null && result != 0) {
                return 1;
            } else {
                return 0;
            }
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 添加一个字符串set,如果key存在就在就最追加,整个set的key有效时间为timeOut时间,单位秒,如果key存在就在可以种继续添加,如果key不存在就创建,,成功返回1,失败或者没有受影响返回0
     *
     * @param key
     * @param value
     * @return
     */
    public static int setExSet(String key, int timeOut, String... value) {
        if (isValueNull(key, value)) {
            return 0;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            Long result = jedis.sadd(key, value);
            jedis.expire(key, timeOut);
            if (result != null && result != 0) {
                return 1;
            } else {
                return 0;
            }
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 添加一个<T>类型到set集合,如果key存在就在就最追加,成功返回1,失败或者没有受影响返回0
     *
     * @param key
     * @param value
     * @return
     */
    @SafeVarargs
    public static <T> int setSet(String key, T... value) {
        if (isValueNull(key, value)) {
            return 0;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            int res = 0;
            for (T t : value) {
                byte[] data = enSeri(t);
                Long result = jedis.sadd(key.getBytes(), data);
                if (result != null && result != 0) {
                    res++;
                }
            }
            if (res != 0) {
                return 1;
            } else {
                return 0;
            }
        } finally {
            returnJedis(jedis);
        }
    }



    /**
     * 缓存一个<T>类型到set集合,如果key存在就在就最追加,整个set的key默认有效时间为1小时,成功返回1,失败或者没有受影响返回0
     *
     * @param key
     * @param value
     * @return
     */
    @SafeVarargs
    public static <T> int setExSet(String key, T... value) {
        if (isValueNull(key, value)) {
            return 0;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            int res = 0;
            for (T t : value) {
                byte[] data = enSeri(t);
                Long result = jedis.sadd(key.getBytes(), data);
                if (result != null && result != 0) {
                    res++;
                }
            }
            jedis.expire(key, DEFAULT_SETEX_TIMEOUT);
            if (res != 0) {
                return 1;
            } else {
                return 0;
            }
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 缓存一个<T>类型到set集合,如果key存在就在就最追加,整个set的key有效时间为timeOut,单位秒,成功返回1,失败或者没有受影响返回0
     *
     * @param key
     * @param value
     * @return
     */
    @SafeVarargs
    public static <T> int setExSet(String key, int timeOut, T... value) {
        if (isValueNull(key, value)) {
            return 0;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            int res = 0;
            for (T t : value) {
                byte[] data = enSeri(t);
                Long result = jedis.sadd(key.getBytes(), data);
                if (result != null && result != 0) {
                    res++;
                }
            }
            jedis.expire(key, timeOut);
            if (res != 0) {
                return 1;
            } else {
                return 0;
            }
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 添加一个Map<K, V>集合,成功返回1,失败返回0
     *
     * @param key
     * @param value
     * @return
     */
    public static <K, V> int setMap(String key, Map<K, V> value) {
        if (value == null || key == null || "".equals(key)) {
            return 0;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            String data = JSON.toJSONString(value);
            if (jedis.set(key, data).equalsIgnoreCase("ok")) {
                return 1;
            } else {
                return 0;
            }
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 缓存一个Map<K, V>集合,成功返回1,失败返回0,默认缓存时间为1小时,以本类的常量DEFAULT_SETEX_TIMEOUT为准
     *
     * @param key
     * @param value
     * @return
     */
    public static <K, V> int setExMap(String key, Map<K, V> value) {
        if (value == null || key == null || "".equals(key)) {
            return 0;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            String data = JSON.toJSONString(value);
            if (jedis.setex(key, DEFAULT_SETEX_TIMEOUT, data).equalsIgnoreCase("ok")) {
                return 1;
            } else {
                return 0;
            }
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 缓存一个Map<K, V>集合,成功返回1,失败返回0,缓存时间以timeout为准,单位秒
     *
     * @param key
     * @param value
     * @param timeout
     * @return
     */
    public static <K, V> int setExMap(String key, Map<K, V> value, int timeout) {
        if (value == null || key == null || "".equals(key)) {
            return 0;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            String data = JSON.toJSONString(value);
            if (jedis.setex(key, timeout, data).equalsIgnoreCase("ok")) {
                return 1;
            } else {
                return 0;
            }
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 获取一个字符串值
     *
     * @param key
     * @return
     */
    public static String get(String key) {
        if (isValueNull(key)) {
            return null;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.get(key);
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 获得一个指定类型的对象
     *
     * @param key
     * @return
     */
    public static <T> T get(String key, Class<T> clazz) {
        if (isValueNull(key)) {
            return null;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();

            byte[] data = jedis.get(key.getBytes());
//            T result = deSeri(data, clazz);
            T result = null;
            if (data != null) {
                result = JSONObject.parseObject(new String(data),clazz);
            }
            return result;
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 获得一个字符串集合,区间以偏移量 START 和 END 指定。 其中 0 表示列表的第一个元素， 1
     * 表示列表的第二个元素，以此类推。 你也可以使用负数下标，以 -1 表示列表的最后一个元素， -2 表示列表的倒数第二个元素，以此类推。
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public static List<String> getList(String key, long start, long end) {
        if (isValueNull(key)) {
            return null;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            List<String> result = jedis.lrange(key, start, end);
            return result;
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 获得一个<T>类型的对象集合,区间以偏移量 START 和 END 指定。 其中 0 表示列表的第一个元素， 1 表示列表的第二个元素，以此类推。
     * 你也可以使用负数下标，以 -1 表示列表的最后一个元素， -2 表示列表的倒数第二个元素，以此类推。
     *
     * @param key
     * @param start
     * @param end
     * @return
     */
    public static <T> List<T> getList(String key, long start, long end, Class<T> clazz) {
        if (isValueNull(key)) {
            return null;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            List<byte[]> lrange = jedis.lrange(key.getBytes(), start, end);
            List<T> result = null;
            if (lrange != null) {
                for (byte[] data : lrange) {
                    if (result == null) {
                        result = new ArrayList<>();
                    }
                    result.add(deSeri(data, clazz));
                }
            }
            return result;
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 获得list中存了多少个值
     *
     * @return
     */
    public static long getListCount(String key) {
        if (isValueNull(key)) {
            return 0;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.llen(key);
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 获得一个List<T>的集合,
     *
     * @param key
     *            键
     * @param clazz
     *            返回集合的类型
     * @return
     * @throws IOException
     */
    public static <T> List<T> getList(String key, Class<T> clazz) throws IOException {
        if (isValueNull(key)) {
            return null;
        }
//        Jedis jedis = null;
//        try {
//            jedis = getJedis();
//            byte[] data = jedis.get(key.getBytes());
//            List<T> result = deSeriList(data, clazz);
//            return result;
//        } finally {
//            returnJedis(jedis);
//        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            byte[] bytes = jedis.get(key.getBytes());
            if (bytes != null) {
                return JSONObject.parseArray(new String(bytes),clazz);
            }
            return null;
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 获得一个字符串set集合
     *
     * @param key
     * @return
     */
    public static Set<String> getSet(String key) {
        if (isValueNull(key)) {
            return null;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            Set<String> result = jedis.smembers(key);
            return result;
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 获得一个字符串set集合
     *
     * @param key
     * @return
     */
    public static <T> Set<T> getSet(String key, Class<T> clazz) {
        if (isValueNull(key)) {
            return null;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            Set<byte[]> smembers = jedis.smembers(key.getBytes());
            Set<T> result = null;
            if (smembers != null) {
                for (byte[] data : smembers) {
                    if (result == null) {
                        result = new HashSet<>();
                    }
                    result.add(deSeri(data, clazz));
                }
            }
            return result;
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 获得集合中存在多少个值
     *
     * @param key
     * @return
     */
    public static long getSetCount(String key) {
        if (isValueNull(key)) {
            return 0;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.scard(key);
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 获得一个Map<v,k>的集合
     *
     * @param key
     * @param v
     * @param k
     * @return
     */
    public static <K, V> Map<K, V> getMap(String key, Class<K> k, Class<V> v) {
        if (key == null || "".equals(key)) {
            return null;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            String data = jedis.get(key);
            @SuppressWarnings("unchecked")
            Map<K, V> result = (Map<K, V>) JSON.parseObject(data);
            return result;
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 删除一个值
     *
     * @param key
     */
    public static void del(String... key) {
        Jedis jedis = null;
        try {
            jedis = getJedis();
            for (int i = 0; i < key.length; i++) {
                jedis.del(key);
            }
        } finally {
            returnJedis(jedis);
        }
    }



    // --------------------------公用方法区------------------------------------
    /**
     * 检查值是否为null,如果为null返回true,不为null返回false
     *
     * @param obj
     * @return
     */
    private static boolean isValueNull(Object... obj) {
        for (int i = 0; i < obj.length; i++) {
            if (obj[i] == null || "".equals(obj[i])) {
                return true;
            }
        }
        return false;
    }

    /**
     * 存储REDIS队列 顺序存储
     * @param <T>
     */
    public static <T> void lpush(String k,T obj ) {

        Jedis jedis = null;
        try {
            jedis = getJedis();
            byte[] key = k.getBytes();
            byte[] value= enSeri(obj);
            jedis.lpush(key, value);
        }  finally {
            //返还到连接池
            returnJedis(jedis);
        }
    }

    /**
     * 取出REDIS队列最后一条
     * @param <T>
     */
    public static <T> T  rpop(String k,Class<T> cls) {

        Jedis jedis = null;
        try {
            jedis = getJedis();
            byte[] key = k.getBytes();
            byte[] rpop = jedis.rpop(key);
            if(rpop==null||rpop.length==0){
                return null;
            }else{
                return deSeri(rpop, cls);}
        }  finally {
            //返还到连接池
            returnJedis(jedis);
        }
    }

    public static Long  llen(String k) {

        Jedis jedis = null;
        try {
            jedis = getJedis();
            byte[] key = k.getBytes();
            return jedis.llen(key);
        }  finally {
            //返还到连接池
            returnJedis(jedis);
        }
    }

    /**
     * 往redis中添加map
     */
    public static void hset(String key, String field, String value) {

        Jedis jedis = null;
        try {
            jedis = getJedis();
            jedis.hset(key, field, value);
        }  finally {
            //返还到连接池
            returnJedis(jedis);
        }
    }

    /**
     * 取出redis中的value
     */
    public static String hget(String key, String field) {

        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.hget(key, field);
        }  finally {
            //返还到连接池
            returnJedis(jedis);
        }
    }

    /**
     * 删除redis中的field
     */
    public static void hdel(String key, String... fields) {

        Jedis jedis = null;
        try {
            jedis = getJedis();
            jedis.hdel(key, fields);
        }  finally {
            //返还到连接池
            returnJedis(jedis);
        }
    }

    /**
     * 推入消息到redis消息通道
     *
     * @param channel
     * @param message
     */
    public static void publish(String channel, String message) {
        Jedis jedis = null;
        try {
            jedis = getJedis();
            jedis.publish(channel, message);
        } finally {
            returnJedis(jedis);
        }
    }

    /**
     * 监听消息通道
     * @param jedisPubSub - 监听任务
     * @param channels - 要监听的消息通道
     */
    public static void subscribe(JedisPubSub jedisPubSub, String... channels) {
        Jedis jedis = null;
        try {
            jedis = getJedis();
            jedis.subscribe(jedisPubSub, channels);
        } finally {
            returnJedis(jedis);
        }
    }


    /**
     * 序列化一个对象
     *
     * @return
     */

    public static <T> byte[] enSeri(T obj) {
        Class<T> cls = (Class<T>) obj.getClass();
        LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
        try {
            Schema<T> schema = getSchema(cls);
            return ProtostuffIOUtil.toByteArray(obj, schema, buffer);
        } catch (Exception e) {
            if(log.isDebugEnabled()){
                e.printStackTrace();
            }
            return null;
        } finally {
            buffer.clear();
        }
    }


    /**
     * 反序列化一个对象
     *
     * @return
     */
    public static <T> T deSeri(byte[] data, Class<T> cls) {
        try {
            T message = objenesis.newInstance(cls);
            Schema<T> schema = getSchema(cls);
            ProtostuffIOUtil.mergeFrom(data, message, schema);
            return message;
        } catch (Exception e) {
            if(log.isDebugEnabled()){
                e.printStackTrace();
            }
            return null;
        }
    }
    private static Objenesis objenesis = new ObjenesisStd(true);
    private static Map<Class<?>, Schema<?>> cachedSchema = new ConcurrentHashMap<>();

    private static <T> Schema<T> getSchema(Class<T> cls) {
        Schema<T> schema = (Schema<T>) cachedSchema.get(cls);
        if (schema == null) {
            schema = RuntimeSchema.createFrom(cls);
            if (schema != null) {
                cachedSchema.put(cls, schema);
            }
        }
        return schema;
    }


    /**
     * 序列化List集合
     *
     * @param list
     * @return
     * @throws IOException
     */
    private static <T> byte[] enSeriList(List<T> list) throws RuntimeException, IOException {
        if (list == null || list.size() == 0) {
            throw new RuntimeException("集合不能为空!");
        }
        @SuppressWarnings("unchecked")
        RuntimeSchema<T> schema = (RuntimeSchema<T>) RuntimeSchema.getSchema(list.get(0).getClass());
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ProtostuffIOUtil.writeListTo(out, list, schema, LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
        byte[] byteArray = out.toByteArray();
        return byteArray;
    }

    /**
     * 反序列化List集合
     *
     * @param data
     * @param clazz
     * @return
     * @throws IOException
     */
    private static <T> List<T> deSeriList(byte[] data, Class<T> clazz) throws IOException {
        if (data == null || data.length == 0) {
            return null;
        }
        RuntimeSchema<T> schema = RuntimeSchema.createFrom(clazz);
        List<T> result = ProtostuffIOUtil.parseListFrom(new ByteArrayInputStream(data), schema);
        return result;
    }

    public static void main(String[] args) throws IOException {
        JedisUtil.poolInit();
//        Jedis jedis = JedisUtil.getJedis();
//        List<PushData> list = new ArrayList<>();
//        for (int i = 0; i < 2; i++) {
//            PushData pushData = new PushData();
//            pushData.setSendType(1);
//            pushData.setUdMsgType(2);
//            pushData.setPower("22");
//            list.add(pushData);
//        }
//        JedisUtil.set("testJ_list",list);
//        List<PushData> testJ_list = JedisUtil.getList("testJ_list", PushData.class);
//        System.out.println(testJ_list.get(0));

//        PushData pushData = new PushData();
//        pushData.setSendType(1);
//        pushData.setUdMsgType(2);
//        pushData.setPower("22");
//        JedisUtil.set("testJ_obj",pushData);
//        PushData testJ_obj = JedisUtil.get("testJ_obj", PushData.class);
//        System.out.println(testJ_obj);

        JedisUtil.set("testJ_str","hello");
        System.out.println(JedisUtil.get("testJ_str"));
    }
}
